package flexcommon.validators
{
	import flexcommon.utils.StringUtils;
	import flexcommon.validators.support.Mod10Check;
	
	import mx.validators.ValidationResult;
	import mx.validators.Validator;
  
  [ResourceBundle("CreditCardValidator")]
  [ResourceBundle("FlexCommon")]
	
	/**
	 * <p>Advanced version of the credit card validator class, the card type
	 * and number are validated against a list of internal regular expressions,
	 * based on Payment Card Industry standards.</p>
	 * 
	 * <p>You must specify the property on the object to be validated 
   * for the validator to do its job properly. A typical use-case would look
   * something like this:</p>
   * 
   * <pre>
   * &lt;fx:AdvancedCreditCardValidator id="ccVal"
   *  source="{cardNbrTextInput}"
   *  property="text"
   *  cardBrand="{someBrand}"
   * &lt;/fx:AdvancedCreditCardValidator&gt;
   * </pre>
	 * 
	 * <p>Refer to the CreditCardValidator.properties class under the config
	 * folder to see the list of regular expression for various card brands.</p>
	 * 
	 * <p>Author: Dimitrios Gianninas</p>
	 */	  
	public class AdvancedCreditCardValidator extends Validator 
	{		
    /**
    * Sets the card brand regular expression to use when validating
    * the card number provided.
    * 
    * <p>Valid values are: VI,MC,AM,DC,CB,JAL,DI,SW,SO,JC,LA,MD,VE,VD</p>
    */
    public var cardBrand:String;
	
		/**
		 * Default constructor
		 */
		public function AdvancedCreditCardValidator() 
    {
			super();
		}
		
		/**
		 * Retrieves the card brand regular expression for validation.
		 * These definitions come from the CreditCardValidator resource bundle file.
		 */
		private function getBrandValidation( brand:String ):String 
		{
			var exp:String = resourceManager.getString( "CreditCardValidator", brand );
      
      if( StringUtils.isEmpty( exp ) )
      {
        return "";
      }
      else
      {
        return exp.substring( 0, exp.length - 1 );  
      }
		}
		
		/**
		 * Overrides of the base class <code>doValidation()</code> method
	 	 * to validate a credit card number.
     * 
     * @param value the object to validate against
     * @return a collection ValidationResult objects if errors occured, 
     * or empty if validation was successful.
		 */
		override protected function doValidation( value:Object ):Array 
		{
			if( !required ) 
			{
				return new Array();
			}
			
      var results:Array = super.doValidation( value );
      
      // if already errors, stop
      if( results.length > 0 ) 
      {
        return results;
      }
      
      var cardNbr:String = this.source[this.property];
      
      // get card type
      var expression:String = getBrandValidation( cardBrand );
      
      //trace( "CCVal2 - cardBrand: " + cardBrand );
      //trace( "CCVal2 - expression: " + expression );
      
      if( StringUtils.isEmpty( expression ) ) 
      {
        results.push( new ValidationResult(
          true, 
          "cardBrand",
          "badCardBrand", 
          resourceManager.getString( "FlexCommon", "CCVAL_BAD_CARD_TYPE" ) ) );
      }
      
      // validate using regular expression
      if( StringUtils.isNotEmpty( expression ) )
      {
        var pattern:RegExp = new RegExp( expression );
        
        //trace( "CCVal2 - cardNum: " + cardNbr );
        //trace( "CCVal2 - test: " + pattern.test( cardNbr ) );
        
        if( !pattern.test( cardNbr ) ) {
          results.push( new ValidationResult(
            true, 
            "cardNumber",
            "badCardNumberForBrand", 
            resourceManager.getString( "FlexCommon", "CCVAL_BAD_CARDNBR_FOR_BRAND" ) ) );
        }
      }     
      
      // perform mod10 check
      var modCheck:Mod10Check = new Mod10Check(); 
      
      if( !modCheck.validate( cardNbr ) ) 
      {
        results.push( new ValidationResult(
          true, 
          "cardNumber",
          "badCardNumber", 
          resourceManager.getString( "FlexCommon", "CCVAL_BAD_CARDNBR" ) ) );
      }
      
      return results;
		}
	}
}